<?php

namespace Yolo\Components\RpcClient;

use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\HandlerStack;
use Hyperf\Guzzle\CoroutineHandler;
use Psr\Http\Message\ResponseInterface;

/**
 * Rpc Client
 * @author LUSHAOMING
 * @date 2024-12-11
 */
class Client implements ClientInterface
{
    public function __construct(
        private readonly string $serviceName,
        private readonly string $url,
        private readonly int $timeout = 10,
    ){}

    /**
     * Get the service name.
     * @return string
     */
    public function getServiceName(): string
    {
        return $this->serviceName;
    }

    /**
     * @param string $endpoint
     * @param array $data
     * @return ResponseInterface
     * @throws GuzzleException
     */
    public function invoke(string $endpoint, array $data): ResponseInterface
    {
       return $this->invokeByNs('Api', $endpoint, $data);
    }

    /**
     * @param string $ns
     * @param string $endpoint
     * @param array $data
     * @return ResponseInterface
     * @throws GuzzleException
     */
    public function invokeByNs(string $ns, string $endpoint, array $data): ResponseInterface
    {
        $endpoint = $this->serviceName . ($ns === 'Api' ? '' : ".$ns").".$endpoint";

        $body = [
            'endpoint' => $endpoint,
            'body' => $data['body'] ?? [],
            'qs' => $data['qs'] ?? [],
            'headers' => $data['headers'] ?? [],
            'path' => $data['path'] ?? [],
            'metadata' => $data['metadata'] ?? [],
        ];

        $client = new GuzzleClient([
            'base_uri' => $this->url,
            'handler' => HandlerStack::create(new CoroutineHandler()),
            'timeout' => $this->timeout,
        ]);

        return $client->post('/', [
            'headers' => [
                'Content-Type' => 'application/json',
                'User-Agent' => 'YoloServiceClient/1.0',
            ],
            'body' => json_encode($body),
        ]);
    }
}
